﻿using Nest;
using PMS.Search.Domain.Entities;
using PMS.Search.Elasticsearch;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ElasticSearchTest
{
    public class UserEsService
    {
        private readonly EsClient _client;
        private readonly EsIndexConfig.Index _index = EsIndexConfig.Instance.TalentIndex;

        public UserEsService(EsClient client)
        {
            _client = client;
        }

        public List<SearchTalent> SearchTalent(string keyword)
        {
            var search = new SearchDescriptor<SearchTalent>()
                .Index(_index.Alias)
                .From(0)
                .Size(5)
                .Sort(s => s
                    .Descending(SortSpecialField.Score)
                    .Script(sc => sc
                        .Type("number")
                        .Script(ss => ss.Source(" return doc['fansTotal'].value + doc['answersTotal'].value "))
                    ))
                ;

            search.Query(q =>
                q.Bool(b =>
                    b.Must(
                        m => m.Term(t => t.Field(f => f.IsDeleted).Value(false)),
                        m => m.Term(t => t.Field(f => f.IsEnable).Value(true)),
                        m => m.Match(ma => ma.Field("nickName.pinyin^1.1").Query(keyword))
                             || m.Match(ma => ma.Field("authTitle.pinyin").Query(keyword))
                    )
                ));

            var result = _client.GetClient().Search<SearchTalent>(search);

            var data = result.Hits.Select(s => s.Source).ToList();

            return data;
        }

        public CreateIndexResponse CreateIndex()
        {
            var resp = _client.GetClient().Indices.Delete(_index.Name);
            return _client.GetClient().Indices.Create(_index.Name, c => c
                .Aliases(ad => ad.Alias(_index.Alias))
                .Settings(s => s
                    .Setting("max_ngram_diff", 20)
                    .Setting("max_result_window", 500000)
                    .Analysis(AnalyzeBuilder.GetAnalysis())
                )
                .Map<SearchTalent>(mm => mm
                .Dynamic(false)
                   .Properties(p => p
                       .Keyword(t => t.Name(n => n.Id))
                       .Keyword(t => t.Name(n => n.UserId))
                       .Number(t => t.Name(n => n.CityCode))
                       .Boolean(t => t.Name(n => n.IsEnable))
                       .Boolean(t => t.Name(n => n.IsDeleted))
                       .Number(t => t.Name(n => n.FansTotal))
                       .Number(t => t.Name(n => n.AnswersTotal))
                       .Text(t => t
                           .Name(n => n.NickName)
                           .Fields(f => f
                                .Text(ft
                                    => ft.Name("cntext")
                                    .Analyzer(AnalyzeBuilder.IkNgramAnalyzer)
                                    .SearchAnalyzer(AnalyzeBuilder.IkSearchAnalyzer))
                                .Text(ft
                                    => ft.Name("pinyin")
                                    .Analyzer(AnalyzeBuilder.IkPinyinAnalyzer)
                                    .SearchAnalyzer(AnalyzeBuilder.IkPinyinSearchAnalyzer))
                           )
                       )
                       .Text(t => t
                           .Name(n => n.AuthTitle)
                           .Fields(f => f
                                .Text(ft
                                    => ft.Name("cntext")
                                    .Analyzer(AnalyzeBuilder.IkNgramAnalyzer)
                                    .SearchAnalyzer(AnalyzeBuilder.IkSearchAnalyzer))
                                .Text(ft
                                    => ft.Name("pinyin")
                                    .Analyzer(AnalyzeBuilder.IkPinyinAnalyzer)
                                    .SearchAnalyzer(AnalyzeBuilder.IkPinyinSearchAnalyzer))
                           )
                       )
                       .Date(t => t.Name(n => n.UpdateTime))
                       .Number(t => t.Name(n => n.Pv))
                       .Number(t => t.Name(n => n.Uv))
                   )
               )
            );

        }
    }
}
